/*****************************************************************************
 *  ENTROPY - emerging network to reduce orwellian potency yield
 *
 *  Copyright (C) 2002 Juergen Buchmueller <pullmoll@stop1984.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software Foundation,
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 *	$Id: localize.c,v 1.2 2005/07/12 23:12:29 pullmoll Exp $
 *****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/errno.h>

char **str_new = NULL;
size_t count_new = 0;

char **str_old = NULL;
size_t count_old;

int add_string(const char *src)
{
	if (0 == count_new) {
		str_new = malloc(sizeof(char *));
		if (NULL == str_new) {
			fprintf(stderr, "malloc(%d) call failed (%s)",
				sizeof(char *), strerror(errno));
			return -1;
		}
	} else {
		str_new = realloc(str_new, (count_new + 1) * sizeof(char *));
		if (NULL == str_new) {
			fprintf(stderr, "realloc(%d) call failed (%s)",
				(count_new + 1) * sizeof(char *), strerror(errno));
			return -1;
		}
	}
	str_new[count_new] = strdup(src);
	if (NULL == str_new[count_new]) {
		fprintf(stderr, "strdup('%s') call failed (%s)",
			src, strerror(errno));
		return -1;
	}
	count_new++;
	return 0;
}

int add_string_old(const char *src, const char *loc)
{
	size_t len = strlen(src) + 1 + strlen(loc) + 1;
	char *tmp = calloc(len, 1);

	if (NULL == tmp) {
		fprintf(stderr, "calloc(%d,%d) call failed (%s)",
			len, 1, strerror(errno));
		return -1;
	}
	snprintf(tmp, len, "%s|%s", src, loc);

	if (0 == count_old) {
		str_old = malloc(sizeof(char *));
		if (NULL == str_old) {
			fprintf(stderr, "malloc(%d) call failed (%s)",
				sizeof(char *), strerror(errno));
			return -1;
		}
	} else {
		str_old = realloc(str_old, (count_old + 1) * sizeof(char *));
		if (NULL == str_old) {
			fprintf(stderr, "realloc(%d) call failed (%s)",
				(count_old + 1) * sizeof(char *), strerror(errno));
			return -1;
		}
	}
	str_old[count_old] = tmp;
	count_old++;
	return 0;
}

int scan_file(char *pathname)
{
	char english[1024], *dst = NULL;
	int state = 0;
	FILE *fp;

	fp = fopen(pathname, "r");
	while (!feof(fp)) {
		int c = fgetc(fp);
		if (-1 == c)
			break;
		switch (state) {
		case 0:	/* expecting L */
			state = ('L' == c) ? 1 : 0;
			break;
		case 1:	/* expecting O */
			state = ('O' == c) ? 2 : 0;
			break;
		case 2:	/* expecting ( */
			state = ('(' == c) ? 3 : 0;
			break;
		case 3:	/* expecting " */
			state = ('"' == c) ? 4 : 0;
			if (4 == state)
				dst = english;
			break;
		case 4:	/* collecting until unescaped " */
			switch (c) {
			case '"':
				*dst = '\0';
				add_string(english);
				state = 6;
				break;
			case '\\':
				state = 5;
				break;
			default:
				*dst++ = c;
			}
			break;
		case 5:	/* escaped character */
			*dst++ = c;
			state = 4;
			break;
		case 6:	/* expecting ) */
			state = 0;
			break;
		}
	}
	fclose (fp);

	return 0;
}

int sort_str(const void *p1, const void *p2)
{
	const char *s1 = *(const char **)p1;
	const char *s2 = *(const char **)p2;
	return strcmp(s1,s2);
}

int main(int argc, char **argv)
{
	char lin1[4096], lin2[4096];
	char pathname[256] = "src", filename[256];
	DIR *dir;
	struct dirent *de;
	struct stat st;
	FILE *fp;
	size_t i, j;

	if (argc < 2) {
		fprintf(stderr, "usage: %s oldloc.xx\n", argv[0]);
		return -1;
	}
	fp = fopen(argv[1], "r");
	if (NULL == fp) {
		fprintf(stderr, "cannot open '%s' (%s)\n", argv[1], strerror(errno));
		return -1;
	}
	while (!feof(fp)) {
		if (NULL == fgets(lin1, sizeof(lin1), fp))
			break;
		if (NULL == fgets(lin2, sizeof(lin2), fp))
			break;
		add_string_old(lin1,lin2);
	}
	fclose(fp);

	dir = opendir(pathname);
	if (NULL == dir) {
		fprintf(stderr, "cannot opendir('%s') (%s)",
			pathname, strerror(errno));
		return 1;
	}
	while (NULL != (de = readdir(dir))) {
		if (0 == strcmp(de->d_name, "."))
			continue;
		if (0 == strcmp(de->d_name, ".."))
			continue;
		sprintf(filename, "%s/%s", pathname, de->d_name);
		if (0 != stat(filename, &st)) {
			fprintf(stderr, "cannot stat('%s') (%s)",
				filename, strerror(errno));
			return 1;
		}
		if (0 == strcmp(filename + strlen(filename) - 2, ".c")) {
			scan_file(filename);
		}
	}
	closedir(dir);

	qsort(str_new, count_new, sizeof(char *), sort_str);

	for (i = 0; i < count_new; i++) {
		size_t len;
		len = strlen(str_new[i]);
		if (i > 0 && 0 == strncmp(str_new[i], str_new[i-1], len)) {
			continue;
		}
		for (j = 0; j < count_old; j++) {
			if (0 == strncmp(str_old[j], str_new[i], len))
				break;
		}
		if (j != count_old) {
			printf("%s\n%s", str_new[i], str_old[j] + len + 2);
		} else {
			printf("%s\nYOUR TRANSLATION HERE\n", str_new[i]);
		}
	}
	for (i = 0; i < count_old; i++) {
		free(str_old[i]);
	}
	for (i = 0; i < count_new; i++) {
		free(str_new[i]);
	}
	free(str_new);

	return 0;
}
